// /*
//  * @Author: WanYiMing
//  * @Date:2024-03-01-13:56
//  * @Description:
//  */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Code.Core.CoreBaseClass;

namespace Code.Core.StateMachine
{
    public abstract class BaseFsm<TFsm> : BaseController where TFsm : BaseFsm<TFsm>
    {
        private Dictionary<Type, object> _states = new Dictionary<Type, object>();

        private State<TFsm> _onState;

        private State<TFsm> _initState;

        public TFsm tFsm;
        public abstract void InitStates();
        public abstract void InitTFsm();


        private void Awake()
        {
            InitTFsm();
            ScanAllStateType();
            InitStates();
        }

        private void Update()
        {
            AutoSwitchState();
            _onState.HoldState();
        }

        private void AutoSwitchState()
        {
            if (_onState.CheckState() && _onState.LastState != null)
            {
                //切换到下一个状态
                AutoSwitchState(_onState.LastState);
            }

            if (_onState.CheckState() && _onState.LastState == null)
            {
                //回到初始状态
                AutoSwitchState(_initState);
            }
        }


        public void AutoSwitchState(State<TFsm> state)
        {
            if (_onState.GetType() == state.GetType())
            {
                return;
            }

            ExeSwitch(_onState, state);
        }


        public void SwitchState(Type type)
        {
            if (_onState is not null&&_onState.GetType() == type)
            {
                return;
            }

            //外部切换是保护的  
            if (_onState is not null&&_onState.IsProtective())
            {
                return;
            }

            State<TFsm> state = GetState(type);
            ExeSwitch(_onState, state);
        }

        public void SwitchState<TState>()
        {
            Type type = typeof(TState);
            SwitchState(type);
        }

        private void ExeSwitch(State<TFsm> onState, State<TFsm> lastState)
        {
            if(onState is not null)onState.OutState();
            lastState.InState();
            _onState = lastState;
        }


        public State<TFsm> GetState<TState>()
        {
            var key = typeof(TState);
            return GetState(key);
        }

        public State<TFsm> GetState(Type type)
        {
            if (_states.TryGetValue(type, out var retInstance))
            {
                return retInstance as State<TFsm>;
            }

            return null;
        }

        public void AddState<TState>() where TState : State<TFsm>, new()
        {
            var key = typeof(TState);
            State<TFsm> state = new TState();
            AddState(state);
        }

        public void AddState(State<TFsm> instance)
        {
            var key = instance.GetType();
            SetState(instance, key);
        }

        private void SetState(State<TFsm> instance, Type key)
        {
            if (_states.ContainsKey(key))
            {
                _states[key] = instance;
            }
            else
            {
                _states.Add(key, instance);
            }

            instance.StateFsm = tFsm;
            SetInitState(instance);
        }

        public void SetLastState<TAState, TBState>()
        {
            State<TFsm> tstate = GetState<TAState>();
            tstate.LastState = GetState<TBState>();
        }

        public void SetLastState(Type taState, Type tbState)
        {
            State<TFsm> tstate = GetState(taState);
            tstate.LastState = GetState(tbState);
        }


        private void SetInitState(State<TFsm> instance)
        {
            if (instance.IsInitState())
            {
                _onState = instance;
                _initState = instance;
            }
        }

        public State<TFsm> GetOnState()
        {
            return _onState;
        }


        private void ScanAllStateType()
        {
            Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
            Type interfaceType = typeof(State<TFsm>); // 获取指定接口类型
            List<State<TFsm>> stateList = new List<State<TFsm>>();
            var classes = assembly.GetTypes()
                .Where(t => interfaceType.IsAssignableFrom(t) && t.IsClass&& !t.IsAbstract)
                .ToList();

            foreach (var cls in classes)
            {
                State<TFsm> instance = (State<TFsm>)Activator.CreateInstance(cls);
                AddState(instance);
            }
        }
    }
}